home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
TIMER.C
< prev
next >
Wrap
Text File
|
1993-10-18
|
6KB
|
269 lines
#include <stdio.h>
#include "global.h"
#include "timer.h"
#include "proc.h"
#include "mbuf.h"
#include "commands.h"
#include "daemon.h"
#include "hardware.h"
#include "socket.h"
/* Head of running timer chain.
* The list of running timers is sorted in increasing order of expiration;
* i.e., the first timer to expire is always at the head of the list.
*/
#ifdef MDEBUG
struct timer *Timers; /* also used in alloc.c */
#else
static struct timer *Timers;
#endif
/* Process that handles clock ticks */
void
timerproc(int i,void *v1,void *v2)
{
struct timer *t, *p, *expired;
void (**vf)(void);
int i_state;
for(;;){
i_state = dirps(); /* Tick is modified by an interrupt */
while(!Tick) {
pwait(&Tick);
}
restore(i_state);
Tick = 0; /* */
if(!istate()) {
restore(1);
#ifdef MDEBUG
usputs(Current->output,"\ntimer: ints were off\n\n");
usflush(Current->output); /* make sure it gets out */
#endif
}
/* Call the functions listed in config.c */
for(vf = Cfunc; *vf != NULL; vf++) {
(*vf)();
}
usflush(Current->output); /* Flush current session output */
pwait(NULL); /* Let them all do their writes */
if(Timers == NULLTIMER) {
/* No active timers, all done */
continue;
}
/* Initialize null expired timer list */
expired = NULLTIMER;
/* Move expired timers to expired list. Note use of
* subtraction and comparison to zero rather than the
* more obvious simple comparison; this avoids
* problems when the clock count wraps around.
*/
while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0) {
if(Timers->next == Timers) {
dirps();
iostop();
#ifdef MDEBUG
printf("\nTimer loop at %lx\n\n",(long)Timers);
#else
printf("\nTimer loop\n\n");
#endif
exit(251);
}
/* Save Timers since stop_timer will change it */
t = Timers;
stop_timer(t);
/* Add to expired timer list */
if(expired == NULLTIMER) {
expired = t;
} else {
for(p = expired ; p->next != NULLTIMER ; p = p->next) ;
p->next = t; /* place at end of chain */
}
t->next = NULLTIMER;
}
/* Now go through the list of expired timers, removing each
* one and kicking the notify function, if there is one
* Note that the state should ne TIMER_STOP. We just stopped
* it remember? Now is someone else changed it, ignore timer.
*/
while((t = expired) != NULLTIMER) {
expired = t->next;
if(t->state == TIMER_STOP) {
t->state = TIMER_EXPIRE;
if(t->func) {
(*t->func)(t->arg);
}
}
}
pwait(NULL); /* Let them run before handling more ticks */
}
}
/* Start a timer */
void
start_timer(struct timer *t)
{
struct timer *tnext, *tprev = NULLTIMER;
if(t == NULLTIMER) {
return;
}
if(t->state == TIMER_RUN) {
stop_timer(t);
}
if(t->duration == 0) {
/* A duration value of 0 disables the timer */
return;
}
t->expiration = Clock + t->duration;
t->state = TIMER_RUN;
/* Find right place on list for this guy. Once again, note use
* of subtraction and comparison with zero rather than direct
* comparison of expiration times.
*/
for(tnext = Timers; tnext != NULLTIMER; tprev = tnext, tnext = tnext->next) {
if((tnext->expiration - t->expiration) >= 0) {
break;
}
}
/* At this point, tprev points to the entry that should go right
* before us, and tnext points to the entry just after us. Either or
* both may be null.
*/
if(tprev == NULLTIMER) {
Timers = t; /* Put at beginning */
} else {
tprev->next = t;
}
t->next = tnext;
}
/* Stop a timer */
void
stop_timer(struct timer *timer)
{
struct timer *t, *tlast = NULLTIMER;
if(timer == NULLTIMER || timer->state != TIMER_RUN) {
return;
}
/* Verify that timer is really on list */
for(t = Timers; t != NULLTIMER; tlast = t, t = t->next) {
if(t == timer) {
break;
}
}
if(t == NULLTIMER) {
/* Should probably panic here */
return;
}
/* Delete from active timer list */
if(tlast != NULLTIMER) {
tlast->next = t->next;
} else {
Timers = t->next; /* Was first on list */
}
t->state = TIMER_STOP;
}
/* Return millisecs remaining on this timer */
int32
read_timer(struct timer *t)
{
int32 remaining;
if(t == NULLTIMER || t->state != TIMER_RUN) {
return 0;
} else {
remaining = t->expiration - Clock;
}
return (remaining <= 0) ? 0 : (remaining * MSPTICK);
}
void
set_timer(struct timer *t,int32 interval)
{
if(t == NULLTIMER) {
return;
}
/* Round up small nonzero intervals to one tick */
t->duration = (interval != 0) ? 1 + (interval + MSPTICK - 1) / MSPTICK : 0;
}
/* Delay process for specified number of millisecs
* normally returns 0, if aborted by alarm returning -1 */
int
pause(int32 ms)
{
int val;
if(Curproc == NULLPROC || ms == 0) {
return 0;
}
alarm(ms);
/* The actual event doesn't matter, since we'll be alerted */
while(Curproc->alarm.state == TIMER_RUN) {
if((val = (int)pwait(Curproc)) != 0) {
break;
}
}
alarm(0L); /* Make sure it's stopped, in case we were killed */
return (val == EALARM) ? 0 : -1;
}
static void
t_alarm(void *x)
{
alert((struct proc *)x,(void *)EALARM);
}
/* Send signal to current process after specified number of millisecs */
void
alarm(int32 ms)
{
if(Curproc != NULLPROC) {
set_timer(&Curproc->alarm,ms);
Curproc->alarm.func = t_alarm;
Curproc->alarm.arg = Curproc;
start_timer(&Curproc->alarm);
}
}
/* Convert time count in seconds to printable days:hr:min:sec format */
char *
tformat(int32 t)
{
static char buf[20];
char *cp = buf, minus = 0;
unsigned int days, hrs, mins, secs;
if(t < 0) {
t = -t;
minus = 1;
}
secs = (int)(t % 60);
t /= 60;
mins = (int)(t % 60);
t /= 60;
hrs = (int)(t % 24);
t /= 24;
days = (int)(t);
if(minus) {
*cp++ = '-';
}
sprintf(cp,"%ud:%02uh:%02um:%02us",days,hrs,mins,secs);
return buf;
}